import java.time.LocalDateTime;
import java.util.concurrent.*;

@SuppressWarnings("all")
public class Demo {

    // 1. Executors.newFixedThreadPool：创建⼀个固定⼤⼩的线程池，可控制并发的线程数，超出的线程会在队列中等待；
    public static void main1(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });

        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });
    }

    // 2. Executors.newCachedThreadPool：创建⼀个可缓存的线程池，若线程数超过处理所需，缓存⼀段时间后会回收，若线程数不够，则新建线程；
    public static void main2(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            service.submit(() -> {
                System.out.println("i : " + finalI + "|线程名称：" + Thread.currentThread().getName());
            });
        }
    }

    // 3. Executors.newSingleThreadExecutor：创建单个线程数的线程池，它可以保证先进先出的执⾏顺序；
    // 延迟执行
    public static void main3(String[] args) {
        //创建线程池
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务的时间：" + LocalDateTime.now());
        //执行定时任务（延迟3s执行）只执行一次
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行子任务：" + LocalDateTime.now());
            }
        }, 3, TimeUnit.SECONDS);
    }

    // 固定频率执行
    public static void main4(String[] args) {
        //创建线程池
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务时间：" + LocalDateTime.now());
        //2s之后开始执行定时任务，定时任务每隔4s执行一次
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务：" + LocalDateTime.now());
            }
        }, 2, 4, TimeUnit.SECONDS);
    }

    // 4. Executors.newScheduledThreadPool：创建⼀个可以执⾏延迟任务的线程池；
    public static void main5(String[] args) {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        System.out.println("添加任务的时间:" + LocalDateTime.now());
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行时间：" + LocalDateTime.now());
            }
        }, 2, TimeUnit.SECONDS);
    }

    // 5. Executors.newSingleThreadScheduledExecutor：创建⼀个单线程的可以执⾏延迟任务的线程池；
    public static void main6(String[] args) {
        ExecutorService service = Executors.newSingleThreadScheduledExecutor();
        for (int i = 0; i < 10; i++) {
            service.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程名：" + Thread.currentThread().getName());
                }
            });
        }
    }

    // 6. Executors.newWorkStealingPool：创建⼀个抢占式执⾏的线程池（任务执⾏顺序不确定）【JDK1.8 添加】。
    public static void main7(String[] args) {
        ExecutorService service = Executors.newWorkStealingPool();
        for (int i = 0; i < 10; i++) {
            service.submit(() -> {
                System.out.println("线程名" + Thread.currentThread().getName());
            });

            while (!service.isTerminated()) {
            }
        }
    }

    // 7. ThreadPoolExecutor：最原始的创建线程池的⽅式，它包含了 7 个参数可供设置，后⾯会详细讲。
    static class MyOOMClass {
        // 1M 空间（M KB Byte）
        private byte[] bytes = new byte[1 * 1024 * 1024];
    }

    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(15 * 1000);
        ExecutorService service = Executors.newCachedThreadPool();
        Object[] objects = new Object[15];
        for (int i = 0; i < 15; i++) {
            final int finalI = i;
            service.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(finalI * 200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    MyOOMClass myOOMClass = new MyOOMClass();
                    objects[finalI] = myOOMClass;
                    System.out.println("任务：" + finalI);
                }
            });
        }
    }
}
